/******************************************************************************
*
*  Copyright (C)  Chen Ming, All right Reserved
*
*  Current Maintainer: Chen Ming.
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Library General Public
*  License as published by the Free Software Foundation; either
*  version 2 of the License, or (at your option) any later version.
*
*  This library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*  Library General Public License for more details.
*
*  FILE NAME:      SpinEdit.c
*  PROGRAMMER:     ming.c
*  Date of Creation:   2006/08/8
*
*  DESCRIPTION:
*  
*  NOTE:
*
*  FUNCTIONS LIST:
* -----------------------------------------------------------------------------
*  eg.  CreateWindow("SpinEdit",NULL,WS_BORDER|WS_VSCROLL|WS_TABSTOP,200,60,100,20,hWnd,0,"1.2  20 1.100  1.55 ");
* -----------------------------------------------------------------------------
* 
*  MODIFICATION HISTORY
*     LastModify  2006/10/30
******************************************************************************/
#include <string.h>
#include "mingui.h"
//---------------------------------------------------------------------------
typedef struct t_SpinEdit
{ int fbitcount;
  float min,max,step,value;
}TSpinEdit;
//---------------------------------------------------------------------------
void SpinEditRepaint(HWND hWnd)
{ HDC dc=BeginPaint(hWnd);
  TSpinEdit *edt=(TSpinEdit *)WndClsBuf(hWnd);
  char strbuf[16];
  if(edt->fbitcount>0)
  { FloatToStr(strbuf,0,edt->fbitcount,edt->value);
  }
  else
  { IntToStr(strbuf,(int)edt->value);
  }
  if(WndGetAttr(hWnd,WS_DISABLED))
  {  SetColor (dc, CL_DARKGRAY);
  }
  else if(WndGetAttr(hWnd,WS_FOCUS))
  { swap(((TWndCanvas *)dc)->Pen.Background,((TWndCanvas *)dc)->Pen.Foreground);
    ClearRect(dc,0,0,crWidth(hWnd),crHeight(hWnd));
  }
 
  DrawText(dc,0,0,crWidth(hWnd),crHeight(hWnd),strbuf,alCenter|alMiddle);

  EndPaint(hWnd);
}
//---------------------------------------------------------------------------
void SpinEditFormat(HWND obj,TSpinEdit *edt,char *fmt)
{ bool digital=true;
  char ch;
  float data[4]={0,0,0,0},fbit;
  int i,dotcount,fbitcount[4]={0,0,0};
  if(!fmt)return;
  for(i=0;i<4;i++)
  { for(ch=*fmt;ch==32;ch=*++fmt);
    for(ch=*fmt,dotcount=0,fbit=(float)0.1;digital&&ch!=32&&ch!=0;ch=*++fmt)
    {    if(ch>='0' && ch<='9')
         { if(dotcount==0) data[i]=data[i]*10 + ch-'0';
           else if (dotcount==1)
           { data[i]=data[i] + fbit*(ch-'0');
             fbit*=(float)0.1;
             fbitcount[i]++;
           }
         }
         else if(ch=='.') dotcount++;
         else  digital=false;
    }
  }
  if(digital)
  { if(fbitcount[0]>=fbitcount[1] && fbitcount[0]>=fbitcount[2])
      edt->fbitcount=fbitcount[0];
    else if(fbitcount[1]>=fbitcount[0] && fbitcount[1]>=fbitcount[2])
      edt->fbitcount=fbitcount[1];
    else edt->fbitcount=fbitcount[2];
    edt->min=data[0];
    edt->max=data[1];

    edt->step=data[2];
    edt->value=data[3];
    if(edt->value>edt->max)edt->value=edt->max;
    else if(edt->value<edt->min)edt->value=edt->min;
  }
}
//---------------------------------------------------------------------------
float SpinEdit_Read(HWND hWnd)
{  if(hWnd)
   { TSpinEdit *edt=(TSpinEdit *)WndClsBuf(hWnd);
     return edt->value;
   }
   else return 0;
}
//---------------------------------------------------------------------------
void SpinEdit_Write(HWND hWnd,float value)
{ if(hWnd)
  {  TSpinEdit *edt=(TSpinEdit *)WndClsBuf(hWnd);
     if(edt->value!=value && value<=edt->max && value>=edt->min)
     { edt->value=value;
       Invalidate(hWnd);
     }
  }
}
//---------------------------------------------------------------------------
void SpinEditCreate(HWND hWnd)
{ TSpinEdit *edt=(TSpinEdit *)WndClsBuf(hWnd);
  memset(edt,0,sizeof(TSpinEdit));
  SpinEditFormat(hWnd,edt,(char*)WndExtraData(hWnd));
}
//---------------------------------------------------------------------------
static HRESULT CALLBACK SpinEditProc(HWND hWnd,UINT Message,WPARAM WParam,LPARAM LParam)
{ 
  switch(Message)
  { 
 	 case WM_VSCROLL:
		    if((int)LParam>0) SpinEditProc(hWnd,WM_KEYDOWN,VK_DOWN,0);
			else SpinEditProc(hWnd,WM_KEYDOWN,VK_UP,0);
  		  return 0;	

     case WM_KEYDOWN:
          { TSpinEdit *edt=(TSpinEdit *)WndClsBuf(hWnd);
            switch(WParam)
            { case VK_UP:    
                    if(edt->value==edt->min)edt->value=edt->max;
                    else
                    {  edt->value-=edt->step;
                       if(edt->value<edt->min)edt->value=edt->min;
                    }
					CMD_NotifyParent(hWnd,CM_CHANGED); 
                    Invalidate(hWnd);
                  return 0;
              case VK_DOWN:  
                    if(edt->value==edt->max)edt->value=edt->min;
                    else
                    { edt->value+=edt->step;
                      if(edt->value>edt->max)edt->value=edt->max;
                    }
					CMD_NotifyParent(hWnd,CM_CHANGED); 
                    Invalidate(hWnd);
                  return 0;
            }
          }
          break;

     case WM_CREATE: 
            SpinEditCreate(hWnd);
          return 0;

     case WM_PAINT:
		    SpinEditRepaint(hWnd);
		  return 0;

     case WM_ENABLE:
     case WM_SETFOCUS:
	 case WM_KILLFOCUS:
		    Invalidate(hWnd);
          return 0;


  }
  return DefWindowProc(hWnd,Message,WParam,LParam);
}
//---------------------------------------------------------------------------
void CM_RegisterSpinEdit(void)
{  TWNDCLASS wc;
   memset(&wc,0,sizeof(wc));
   wc.dwStyle=WS_BORDER_LOWERED;
   wc.clForeground=CL_WINDOWTEXT;
   wc.clBackground=CL_WHITE;
   wc.cbWndExtra=sizeof(TSpinEdit);
   wc.lpfnWndProc=SpinEditProc;
   wc.lpszClassName="SpinEdit";
   RegisterClass(&wc);
}
//---------------------------------------------------------------------------

